/**
 * 存sessionStorage
 */
export const setStore = (name, content) => {
	if (!name) return
	if (typeof content !== 'string') {
		content = JSON.stringify(content)
	}
	window.sessionStorage.setItem(name, content)
}

/**
 * 取sessionStorage
 */
export const getStore = name => {
	if (!name) return
	return window.sessionStorage.getItem(name)
}

/**
 * 删sessionStorage
 */
export const removeStore = name => {
	if (!name) return
	window.sessionStorage.removeItem(name)
}

/**
 * 存localStorage
 */
export const setLocalStore = (name, content) => {
	if (!name) return
	if (typeof content !== 'string') {
		content = JSON.stringify(content)
	}
	window.localStorage.setItem(name, content)
}

/**
 * 取localStorage
 */
export const getLocalStore = name => {
	if (!name) return
	return window.localStorage.getItem(name)
}

/**
 * 删localStorage
 */
export const removeLocalStore = name => {
	if (!name) return
	window.localStorage.removeItem(name)
}

/**
 * 存cookies
 */
export const setCookie = (name, value, exdays) => {
	let exp = new Date()
	exp.setTime(exp.getTime() + exdays * 24 * 60 * 60 * 1000)
	document.cookie = name + '=' + escape(value) + ';path=/;expires=' + exp.toGMTString()
}

/**
 * 取cookies
 */
export const getCookie = name => {
	let reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)')
	let arr = document.cookie.match(reg)
	if (arr) {
		return unescape(arr[2])
	} else {
		return null
	}
}

/*
 * 删cookie
 */
export const delCookie = name => {
	let exp = new Date()
	exp.setTime(exp.getTime() - 1)
	let cval = getCookie(name)
	if (cval != null) {
		document.cookie = name + '=' + cval + ';expires=' + exp.toGMTString()
	}
}

/**
 * 清除所有cookies
 */
export const clearCookie = () => {
	let keys = document.cookie.match(/[^ =;]+(?==)/g)
	if (keys) {
		for (let i = keys.length; i--; ) {
			document.cookie = keys[i] + '=0;expires=' + new Date(0).toUTCString()
		}
	}
}

/**
 * 替换返回数据中的部分字符串
 */
export const replaceStr = (data, obj) => {
	let resData = JSON.stringify(data)
	for (let i in obj) {
		resData = resData.replace(new RegExp('\\b' + i + '\\b', 'gi'), obj[i])
	}
	resData = JSON.parse(resData)
	return resData
}

/**
 * @desc 递归提取某个元素
 * @param data 原始数组
 * @param name 提取元素名称
 * @param children 子数组名称
 * @param emptyArr 空数组
 * @return 返回数组
 */
export const getRecursiveByName = (data, name, children, emptyArr = []) => {
	Array.from(data).forEach(val => {
		emptyArr.push(val[name])
		if (val[children] && val[children].length > 0) {
			let childFlowIdArr = getRecursiveByName(val, name, children, emptyArr)
			emptyArr.concat(childFlowIdArr)
		}
	})
	return emptyArr
}

/**
 * 格式化时间 返回[年,月,日,时,分,秒]数组, val若存在返回类似 2018-01-02 10:00:00
 */
export const changeDate = (timeStamp, connect) => {
	if (!timeStamp) return
	let date = new Date(Number(timeStamp))
	let year, month, day, hour, minute, seconds
	year = date.getFullYear()
	month = date.getMonth() + 1
	day = date.getDate()
	hour = date.getHours()
	minute = date.getMinutes()
	seconds = date.getSeconds()
	date = null
	let arr = [year, month, day, hour, minute, seconds]
	for (let i = 0; i < arr.length; i++) {
		if (arr[i] < 10) {
			arr[i] = '0' + arr[i]
		} else {
			arr[i] = String(arr[i])
		}
	}
	if (connect) {
		return `${arr[0]}${connect}${arr[1]}${connect}${arr[2]} ${arr[3]}:${arr[4]}:${arr[5]}`
	}
	return arr
}

/**
 * @param arra 时间戳
 * @param mark 分隔符 例如 '/'
 * @return 返回格式  例如 '2019/10/01'
 */
export const formatDate = (arra, mark = '/') => {
	if (arra) {
		let arr = changeDate(arra)
		return `${arr[0]}${mark}${arr[1]}${mark}${arr[2]}`
	} else {
		return ``
	}
}

/**
 * @param arra 时间戳
 * @return 返回格式  例如 '2019年10月01日'
 */
export const formatCharDate = arra => {
	if (arra) {
		let arr = changeDate(arra)
		return `${arr[0]}年${arr[1]}月${arr[2]}日`
	} else {
		return ` `
	}
}

/**
 * @param arra 时间戳
 * @return 返回格式  例如 '2019/10/01 00:00:00'
 */
export const formatTime = (arra, mark = '/') => {
	if (arra) {
		let arr = changeDate(arra)
		return `${arr[0]}${mark}${arr[1]}${mark}${arr[2]} ${arr[3]}:${arr[4]}:${arr[5]}`
	} else {
		return ``
	}
}

/**
 * @desc  数组元素去重
 * @param {Array} 数组
 */
export const removeDuplicateNode = arr => {
	return [...new Set(arr)]
}

/**
 * @desc  对象数组元素去重
 * @param {Array} 对象数组
 */
export const removeDuplicateObject = arr => {
	let temp = arr.map(item => JSON.stringify(item))
	temp = Array.from(new Set(temp))
	return temp.map(item => JSON.parse(item))
}

/**
 * @desc  比较对象值是否都相等
 * @param {Object} x 对象1
 * @param {Object} y 对象2
 * @return {Boolean} true 为相等，false 为不等
 */
export const equalsObject = (x, y) => {
	var f1 = x instanceof Object
	var f2 = y instanceof Object
	if (!f1 || !f2) {
		return x === y
	}
	if (Object.keys(x).length !== Object.keys(y).length) {
		return false
	}
	var newX = Object.keys(x)
	for (var p in newX) {
		p = newX[p]
		var a = x[p] instanceof Object
		var b = y[p] instanceof Object
		if (a && b) {
			equalsObject(x[p], y[p])
		} else if (x[p] != y[p]) {
			return false
		}
	}
	return true
}

/**
 * @desc 递归实现深度克隆---对象/数组
 * @param {Object/Array} target
 */
export const deepClone = target => {
	//判断拷贝的数据类型
	//初始化变量result 成为最终克隆的数据
	let result,
		targetType = Object.prototype.toString.call(target).slice(8, -1)
	if (targetType === 'Object') {
		result = {}
	} else if (targetType === 'Array') {
		result = []
	} else {
		return target
	}
	//遍历目标数据
	for (let i in target) {
		//获取遍历数据结构的每一项值。
		let value = target[i]
		//判断目标结构里的每一值是否存在对象/数组
		if (
			Object.prototype.toString.call(value).slice(8, -1) === 'Object' ||
			Object.prototype.toString.call(value).slice(8, -1) === 'Array'
		) {
			//对象/数组里嵌套了对象/数组
			//继续遍历获取到value值
			result[i] = deepClone(value)
		} else {
			//获取到value值是基本的数据类型或者是函数。
			result[i] = value
		}
	}
	return result
}

/**
 * @desc 对象key value交换
 * @param {Object} obj 对象
 * @return {Object} newObj 新对象
 */
export const swapPositionObject = obj => {
	let newObj = {}
	for (const key in obj) {
		// eslint-disable-next-line no-prototype-builtins
		if (obj.hasOwnProperty(key)) {
			const item = obj[key]
			newObj[item] = key
		}
	}
	return newObj
}

/**
 * @desc 函数防抖
 * @param {Function} func 函数
 * @param {Number} wait 延迟执行毫秒数
 * @param {Boolean} immediate true 表立即执行，false 表非立即执行
 */
export const debounce = (func, wait, immediate = false) => {
	let timeout
	return function () {
		let context = this
		let args = arguments
		if (timeout) clearTimeout(timeout)
		if (immediate) {
			var callNow = !timeout
			timeout = setTimeout(() => {
				timeout = null
			}, wait)
			if (callNow) func.apply(context, args)
		} else {
			timeout = setTimeout(function () {
				func.apply(context, args)
			}, wait)
		}
	}
}

/**
 * @desc 函数节流
 * @param {Function} func 函数
 * @param {Number} wait 延迟执行毫秒数
 * @param {Number} type 1 表时间戳版，2 表定时器版
 */
export const throttle = (func, wait = 500, type = 2) => {
	let previous = 0
	let timeout
	return function () {
		let context = this
		let args = arguments
		if (type === 1) {
			let now = Date.now()
			if (now - previous > wait) {
				func.apply(context, args)
				previous = now
			}
		} else if (type === 2) {
			if (!timeout) {
				timeout = setTimeout(() => {
					timeout = null
					func.apply(context, args)
				}, wait)
			}
		}
	}
}

/**
 * @desc 处理async await异常
 * @param {Promise} promise
 */
export const awaitWrap = promise => {
	return promise.then(data => [null, data]).catch(err => [err, null])
}

/**
 * @desc 由一个组件，向上找到最近的指定组件
 * @param {*} context 组件
 * @param {*} componentName  指定Name组件
 */
export const findComponentUpward = (context, componentName) => {
	let parent = context.$parent
	let name = parent.$options.name

	while (parent && (!name || [componentName].indexOf(name) < 0)) {
		parent = parent.$parent
		if (parent) name = parent.$options.name
	}
	return parent
}

/**
 * @desc 由一个组件，向上找到所有的指定组件
 * @param {*} context 组件
 * @param {*} componentName  指定Name组件
 */
export const findComponentsUpward = (context, componentName) => {
	let parents = []
	const parent = context.$parent

	if (parent) {
		if (parent.$options.name === componentName) parents.push(parent)
		return parents.concat(findComponentsUpward(parent, componentName))
	} else {
		return []
	}
}

/**
 * @desc 由一个组件，向下找到最近的指定组件
 * @param {*} context 组件
 * @param {*} componentName  指定Name组件
 */
export const findComponentDownward = (context, componentName) => {
	const childrens = context.$children
	let children = null

	if (childrens.length) {
		for (const child of childrens) {
			const name = child.$options.name

			if (name === componentName) {
				children = child
				break
			} else {
				children = findComponentDownward(child, componentName)
				if (children) break
			}
		}
	}
	return children
}

/**
 * @desc 由一个组件，向下找到所有指定的组件
 * @param {*} context 组件
 * @param {*} componentName  指定Name组件
 */
export const findComponentsDownward = (context, componentName) => {
	return context.$children.reduce((components, child) => {
		if (child.$options.name === componentName) components.push(child)
		const foundChilds = findComponentsDownward(child, componentName)
		return components.concat(foundChilds)
	}, [])
}

/**
 * @desc 由一个组件，找到指定组件的兄弟组件
 * @param {*} context 组件
 * @param {*} componentName  指定Name组件
 * @param {Boolean} exceptMe 是否排除自身
 */
export const findBrothersComponents = (context, componentName, exceptMe = true) => {
	let res = context.$parent.$children.filter(item => {
		return item.$options.name === componentName
	})
	let index = res.findIndex(item => item._uid === context._uid)
	if (exceptMe) res.splice(index, 1)
	return res
}
